# -*- coding: utf-8 -*-
"""
智慧职教MOOC视频下载器 - 主程序
整合所有模块，提供统一的下载入口
"""

import time
import signal
import sys
from typing import Optional
from browser_manager import BrowserManager
from pagination_manager import PaginationManager
from course_processor import CourseProcessor
from download_stats import stats_manager
from config import config
from logger import logger
from exceptions import BrowserConnectionError, PaginationError, MOOCDownloaderError


class MOOCDownloader:
    """MOOC下载器主类"""
    
    def __init__(self):
        self.browser_manager: Optional[BrowserManager] = None
        self.pagination_manager: Optional[PaginationManager] = None
        self.course_processor: Optional[CourseProcessor] = None
        self._interrupt_requested = False
        
        # 注册信号处理器
        signal.signal(signal.SIGINT, self._signal_handler)
        signal.signal(signal.SIGTERM, self._signal_handler)
        
    def _signal_handler(self, signum, frame):
        """处理中断信号"""
        logger.warning("收到中断信号，正在安全退出...")
        self._interrupt_requested = True
    
    def initialize(self) -> bool:
        """初始化所有组件"""
        logger.info("🚀 智慧职教MOOC视频下载器启动")
        logger.info("=" * 60)
        
        try:
            # 初始化浏览器
            self.browser_manager = BrowserManager()
            if not self.browser_manager.initialize_browser():
                raise BrowserConnectionError("浏览器初始化失败")
            
            driver = self.browser_manager.get_driver()
            main_window = self.browser_manager.get_main_window()
            
            # 初始化其他组件
            self.pagination_manager = PaginationManager(driver)
            self.course_processor = CourseProcessor(driver, main_window)
            
            logger.success("所有组件初始化完成")
            return True
            
        except Exception as e:
            logger.error(f"初始化失败: {e}")
            return False
    
    def run(self) -> bool:
        """执行主要下载流程"""
        if not self.initialize():
            return False
        
        try:
            return self._execute_download_workflow()
            
        except KeyboardInterrupt:
            logger.warning("用户中断程序")
            return False
        except Exception as e:
            logger.error(f"程序异常: {e}")
            stats_manager.add_global_error(str(e))
            return False
        finally:
            self._cleanup()
    
    def _execute_download_workflow(self) -> bool:
        """执行下载工作流"""
        driver = self.browser_manager.get_driver()
        
        # 导航到主页面
        logger.progress("正在导航到课程列表页面...")
        driver.get(config.MOOC_INDEX_URL)
        time.sleep(3)
        
        # 获取分页信息
        try:
            total_pages, current_page, page_links = self.pagination_manager.get_pagination_info()
            stats_manager.total_pages = total_pages
        except Exception as e:
            logger.error(f"获取分页信息失败: {e}")
            stats_manager.add_global_error(f"分页信息获取失败: {e}")
            return False
        
        logger.info(f"发现 {total_pages} 页课程，开始逐页处理...")
        
        # 遍历所有页面
        for page_num in range(1, total_pages + 1):
            if self._interrupt_requested:
                logger.warning("收到中断请求，停止处理")
                break
                
            if not self._process_page(page_num):
                logger.warning(f"第 {page_num} 页处理失败，继续下一页")
                stats_manager.add_global_error(f"第{page_num}页处理失败")
            
            stats_manager.processed_pages += 1
        
        # 完成处理
        stats_manager.finish_session()
        self._show_final_results()
        
        return True
    
    def _process_page(self, page_num: int) -> bool:
        """处理单个页面"""
        logger.info(f"\n{'='*60}")
        logger.info(f"📄 正在处理第 {page_num}/{stats_manager.total_pages} 页的课程")
        logger.info(f"{'='*60}")
        
        try:
            # 跳转到指定页面
            if page_num > 1:
                if not self.pagination_manager.navigate_to_page(page_num):
                    raise PaginationError(f"无法跳转到第{page_num}页")
            
            # 获取当前页面的课程
            courses_info = self.pagination_manager.get_courses_from_current_page()
            
            if not courses_info:
                logger.warning(f"第{page_num}页未找到任何课程")
                return True
            
            # 处理每个课程
            page_successful = self._process_courses_on_page(courses_info, page_num)
            
            logger.info(f"\n📊 第{page_num}页处理完成:")
            logger.info(f"   - 发现课程: {len(courses_info)} 门")
            logger.info(f"   - 成功处理: {page_successful} 门")
            logger.info(f"   - 失败: {len(courses_info) - page_successful} 门")
            
            return True
            
        except Exception as e:
            logger.error(f"处理第{page_num}页时发生错误: {e}")
            return False
    
    def _process_courses_on_page(self, courses_info: list, page_num: int) -> int:
        """处理页面上的所有课程"""
        page_successful = 0
        processed_course_names = set()  # 避免重复处理
        
        for course_info in courses_info:
            if self._interrupt_requested:
                logger.warning("收到中断请求，停止处理当前页面")
                break
                
            course_name = course_info['course_name']
            
            # 检查是否已经处理过
            if course_name in processed_course_names:
                logger.debug(f"跳过已处理的课程: {course_name}")
                continue
            
            try:
                logger.info(f"\n🎯 处理第{page_num}页第{course_info['idx']}门课程: {course_name}")
                
                # 开始统计
                course_stats = stats_manager.start_course_processing(course_name)
                processed_course_names.add(course_name)
                
                # 确保在正确的页面
                self._ensure_correct_page(page_num)
                
                # 处理课程
                success = self.course_processor.process_course(course_info, course_stats)
                
                # 完成统计
                stats_manager.finish_course_processing(course_name, success)
                
                if success:
                    page_successful += 1
                    logger.success(f"课程处理完成: {course_name}")
                else:
                    logger.error(f"课程处理失败: {course_name}")
                    
            except Exception as e:
                logger.error(f"处理课程异常: {course_name} - {e}")
                stats_manager.add_course_error(course_name, str(e))
                stats_manager.finish_course_processing(course_name, False)
            
            # 每处理一个课程后短暂休息
            time.sleep(1)
        
        return page_successful
    
    def _ensure_correct_page(self, page_num: int):
        """确保在正确的页面"""
        driver = self.browser_manager.get_driver()
        
        try:
            driver.get(config.MOOC_INDEX_URL)
            time.sleep(2)
            
            if page_num > 1:
                if not self.pagination_manager.navigate_to_page(page_num):
                    raise PaginationError(f"无法跳转到第{page_num}页")
                    
        except Exception as e:
            logger.warning(f"确保页面正确时出错: {e}")
            raise
    
    def _show_final_results(self):
        """显示最终结果"""
        logger.info("\n🎉 所有页面的课程处理完毕！")
        
        # 显示统计报告
        stats_manager.print_detailed_report()
        
        # 保存详细报告
        report_file = stats_manager.save_report()
        if report_file:
            logger.info(f"📄 详细报告已保存: {report_file}")
        
        # 显示失败率最高的课程
        failed_courses = stats_manager.get_top_failed_courses(3)
        if failed_courses:
            logger.info(f"\n❌ 失败率最高的课程:")
            for i, course in enumerate(failed_courses, 1):
                logger.info(f"   {i}. {course.course_name} (成功率: {course.success_rate:.1%})")
    
    def _cleanup(self):
        """清理资源"""
        logger.progress("正在清理资源...")
        
        try:
            if self.browser_manager and self.browser_manager.check_connection():
                self.browser_manager.close_all_pages()
                logger.success("浏览器页面清理完成")
            else:
                logger.warning("浏览器不可用，跳过页面清理")
                
        except Exception as e:
            logger.error(f"清理时出错: {e}")


def main():
    """主函数"""
    downloader = MOOCDownloader()
    
    try:
        success = downloader.run()
        
        if success:
            logger.success("程序正常完成！")
            return 0
        else:
            logger.error("程序未正常完成")
            return 1
            
    except KeyboardInterrupt:
        logger.warning("程序被用户中断")
        return 130  # 标准的中断退出码
    except Exception as e:
        logger.critical(f"程序严重异常: {e}")
        return 1
    finally:
        logger.info("\n" + "=" * 60)
        logger.info("🏁 程序结束")
        logger.info("=" * 60)


if __name__ == "__main__":
    sys.exit(main()) 